package com.lazy.lib.common;

import com.lazy.lib.util.LoggerUtil;
import org.slf4j.Logger;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 定时检查MonitorThread的在线状态
 * @author luodan
 *
 */
public class MonitorThread implements Runnable {
	
	private static Logger logger = LoggerUtil.getLogMonitor();

	/**
	 * 定时任务
	 */
	private final ScheduledThreadPoolExecutor scheduledPool = (ScheduledThreadPoolExecutor) Executors
			.newScheduledThreadPool(1,  new ThreadFactory()
            {
                AtomicInteger atomic = new AtomicInteger();
                public Thread newThread(Runnable r)
                {
                    return new Thread(r, "AppMonitorThead" + this.atomic.getAndIncrement());
                }
            });
	protected long interval = 60; // 执行间隔， 单位s
    protected AppendInfo appendInfo; // 调用者加入的信息

	public MonitorThread() {

	}
	public MonitorThread(long interval) {
		this.interval = interval;
	}

    public MonitorThread(AppendInfo appendInfo) {
        this.appendInfo = appendInfo;
    }

    public long getInterval() {
		return interval;
	}

	public void setInterval(long interval) {
		this.interval = interval;
	}

    public AppendInfo getAppendInfo() {
        return appendInfo;
    }

    public void setAppendInfo(AppendInfo appendInfo) {
        this.appendInfo = appendInfo;
    }

    /**
	 * shutdown 
	 */
	public void shutdown() {
		try {
			scheduledPool.shutdown();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/** start run the timer task with the scheduledPool */
	public void startRun() {
    	scheduledPool.scheduleAtFixedRate(new MonitorThread(getAppendInfo()), 0, interval, TimeUnit.SECONDS);
	}

	public void run () {
		//logger.info("begin MonitorThread");
		try{
		    StringBuilder sb = new StringBuilder();

            appendThreadInfo(sb);
            appendRuntimeInfo(sb);
            if (appendInfo != null) {
                appendInfo.append(sb);
            }
			logger.info("{}", sb.toString());
        }catch(Exception e){
			logger.error("Error with msg:", e);
        }
		
		//logger.info("end MonitorThread");
	}

    private ThreadGroup getTopThreadGroup() {
        ThreadGroup group =
                Thread.currentThread().getThreadGroup();
        ThreadGroup topGroup = group;

        // 遍历线程组树，获取根线程组
        while ( group != null ) {
            topGroup = group;
            group = group.getParent();
        }
        return topGroup;
    }

    protected StringBuilder appendThreadInfo(StringBuilder sb) {
        ThreadGroup topGroup = getTopThreadGroup();
        sb.append("\nthread info[");
        sb.append("activeGroup=").append(topGroup.activeGroupCount());
        sb.append(", active=").append(topGroup.activeCount());
        sb.append("]");
        // topGroup.list();
        return sb;
    }

    /**
     * 封装内存使用的状态
     * free 表示虚拟机空闲的内存
     * total 虚拟机实际占用的物理内存， -Xms设置
     * max 虚拟机最大可分派的内存   -Xmx设置
     * @param sb
     * @return
     */
    protected StringBuilder appendRuntimeInfo(StringBuilder sb) {
        Runtime runtime = Runtime.getRuntime();
        sb.append("\nmemory info[");
        sb.append("free=").append(runtime.freeMemory()>>20).append("M");
        sb.append(", total=").append(runtime.totalMemory()>>20).append("M");
        sb.append(", max=").append(runtime.maxMemory()>>20).append("M");
        sb.append("]");
        return sb;
    }

    /**
     * AppendInfo
     */
    public static interface AppendInfo {
        /**
         * 格式样子
         * sb.append("\nmemory info[");
         * sb.append("free=").append(10);
         * sb.append(", free=").append(10);
         * sb.append("]");
         * @param sb
         * @return
         */
        public StringBuilder append(StringBuilder sb);
    }

	public static void main(String[] args) {
		logger.info("start...");
		MonitorThread monitorThread = new MonitorThread();
        monitorThread.setAppendInfo(new AppendInfo() {
            @Override
            public StringBuilder append(StringBuilder sb) {
                sb.append("test=====");
                return sb;
            }
        });
        monitorThread.startRun();
        // new MonitorThread().run();

		logger.info("end...");
	}

}
